💡 AI 인사이트

🤖 AI가 여기에 결과를 출력합니다...

댓글 커뮤니티

쿠팡이벤트

이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다.

검색

    로딩 중이에요... 🐣

    [코담] 웹개발·실전 프로젝트·AI까지, 파이썬·장고의 모든것을 담아낸 강의와 개발 노트

    09 포스트 생성 API 작업 | ✅ 편저: 코담 운영자

    9강 - 포스트 생성 API 작업

    생성 API 작업


    ✨ 이번 강의 목표

    • 사용자가 게시물을 작성하고 업로드할 수 있는 API 구현
    • GET/POST 방식 분기 처리 흐름 구현
    • 로그인 인증 유무에 따라 접근 제어
    • 파일 업로드(request.FILES) 및 데이터 저장 이해

    1. 프로젝트 개요

    Django를 기반으로 사용자가 게시글(이미지 + 글)을 등록할 수 있도록 하는 기능을 구현합니다. Cookiecutter로 생성된 Instagram 클론 프로젝트이며, 로그인한 사용자만 게시글 작성이 가능합니다.


    2. URL 설정

    ✅ 설명

    게시물 생성을 위한 URL 경로를 설정합니다. /create/ 경로로 접근 시 post_create 뷰가 호출됩니다. name='post_create'는 템플릿에서 {% url 'posts:post_create' %}로 쉽게 참조할 수 있도록 합니다.

    posts/urls.py

    from django.urls import path
    from . import views
    
    app_name = "posts"
    
    urlpatterns = [
        path('', views.index, name="index"),  # 메인 페이지
        path('create/', views.post_create, name='post_create')  # 게시물 생성 페이지
    ]
    

    post_create URL을 통해 게시물 생성 뷰로 접근합니다.


    3. 게시물 생성 버튼 템플릿

    <!-- 게시물 생성 버튼 -->
    <div class="cursor-pointer transform transition-transform duration-300 hover:scale-110">
        <a href="{% url 'posts:post_create' %}">
            <i class="fa fa-plus-circle text-gray-600 hover:text-blue-500 text-2xl"></i>
        </a>
    </div>
    

    상단 header.html에서 해당 버튼 클릭 시 게시글 생성 페이지로 이동합니다.


    4. 게시물 생성 템플릿 (create.html)

    ✅ 설명

    사용자가 입력할 수 있는 폼을 HTML로 구성합니다. 입력 항목은 이미지 파일과 캡션(내용)입니다. TailwindCSS를 사용해 UI 구성도 깔끔하게 디자인되어 있습니다.

    • form 태그의 enctype="multipart/form-data"는 파일 업로드 시 필수
    • csrf_token은 보안상 필수 요소로 POST 요청 위조 방지에 사용됩니다
    • textareafile input은 각각 caption과 image 입력용

    templates/posts/post_create.html

    {% extends "posts/base.html" %}
    {% load static %}
    
    {% block title %} 포스트 생성 {% endblock title %}
    
    {% block content %}
    <div class="flex justify-center items-center min-h-screen bg-gray-100">
        <div class="w-3/4 aspect-[4/3] bg-white rounded-lg shadow-md p-8">
            <h1 class="text-2xl font-bold text-gray-800 mb-6 text-center">게시글 등록</h1>
    
            <!-- 게시물 등록 폼 -->
            <form action="{% url 'posts:post_create' %}" method="post" enctype="multipart/form-data" class="space-y-6 w-4/6 mx-auto">
                {% csrf_token %}
    
                <div>
                    <label for="id_caption" class="block text-sm font-medium text-gray-700 mb-1">내용</label>
                    <textarea id="id_caption" name="caption" class="w-full border-gray-300 rounded-lg shadow-sm focus:border-indigo-500 focus:ring-indigo-500" rows="12" required></textarea>
                </div>
    
                <div>
                    <label for="id_image" class="block text-sm font-medium text-gray-700 mb-1">사진</label>
                    <input required id="id_image" type="file" name="image" class="w-full file:mr-4 file:py-2 file:px-4 file:rounded-lg file:border-0 file:bg-indigo-600 file:text-white file:font-medium file:cursor-pointer file:hover:bg-indigo-500" />
                </div>
    
                <button type="submit" class="w-full bg-indigo-600 text-white font-semibold rounded-lg py-3 text-center shadow-md hover:bg-indigo-500 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500">등록하기</button>
            </form>
        </div>
    </div>
    {% endblock content %}
    

    enctype="multipart/form-data" 필수이며, CSRF 토큰도 꼭 포함합니다.


    5. 게시물 생성 뷰

    ✅ 설명

    클라이언트 요청이 GET인지 POST인지에 따라 다른 처리를 합니다. GET 요청이면 업로드 폼을 보여주고, POST 요청이면 실제 데이터를 저장합니다.

    • request.user.is_authenticated: 로그인된 사용자인지 검사
    • get_object_or_404: 로그인 사용자의 유효성 검사 및 조회
    • request.FILES['image']: 업로드된 이미지 파일 추출
    • request.POST['caption']: 사용자가 입력한 글 내용 추출
    • Post.objects.create(...): Post 모델 객체를 DB에 저장
    • 저장 후 redirect('posts:index')로 메인 피드로 이동

    인증되지 않은 사용자는 강제로 로그인 페이지로 이동됩니다

    posts/views.py

    from django.shortcuts import render, get_object_or_404, redirect
    from django_instagram.users.models import User as user_model
    from . import models
    
    # 메인 페이지
    def index(request):
        return render(request, 'posts/index.html')
    
    # 게시물 생성 뷰
    def post_create(request):
        if request.method == "GET":
            return render(request, 'posts/post_create.html')
    
        elif request.method == "POST":
            if request.user.is_authenticated:
                user = get_object_or_404(user_model, pk=request.user.id)
                image = request.FILES['image']
                caption = request.POST['caption']
    
                # 게시물 저장
                new_post = models.Post.objects.create(
                    author=user,
                    image=image,
                    caption=caption,
                )
                new_post.save()
    
                return redirect('posts:index')
            else:
                return redirect('users:login')
    

    인증되지 않은 사용자가 접근할 경우 로그인 페이지로 리디렉션됩니다.


    6. 게시물 생성 전체 흐름 요약

    ✅ 설명

    사용자가 게시물을 생성할 때 어떤 요청과 응답이 오가는지 전체적인 흐름을 순서대로 설명합니다. 실제 실무에서도 API 동작 흐름을 먼저 파악하고 뷰를 작성해야 합니다.

    1. 로그인된 사용자가 "+" 버튼 클릭
    2. post_create URL로 이동
    3. GET 요청 시 → post_create.html 렌더링
    4. POST 요청 시 → 폼 데이터 수신 및 저장
    5. 업로드된 이미지 파일은 request.FILES['image']에서 가져옴
    6. 텍스트 내용은 request.POST['caption']에서 가져옴
    7. 저장 후 → 메인 피드(posts:index)로 리디렉션

    ✅ 정리

    • 로그인 인증 여부 체크 (request.user.is_authenticated)
    • request.FILES는 파일 업로드를 처리하기 위한 전용 객체
    • form에는 반드시 enctype="multipart/form-data" 필요
    • 게시물 저장 후 redirect로 리다이렉트하여 UX 흐름 유지

    👉 다음 강의에서는 실제 모델 구조를 기반으로 업로드 이미지의 미디어 처리 및 피드에 출력하는 기능을 구현합니다.

    TOP
    preload preload